package com.ys.controller.api.inter;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

import javax.servlet.http.HttpServletRequest;

import com.ys.entity.sys.*;
import com.ys.enume.sys.YsGridColEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.bo.util.MapUtil;
import com.ys.entity.flow.YspDefNode;
import com.ys.entity.flow.YspTaskAudit;
import com.ys.entity.flow.YspTaskAuditUser;
import com.ys.enume.flow.YsProcInstEnum;
import com.ys.enume.flow.YspDefNodeEnum;
import com.ys.enume.flow.YspTaskAuditEnum;
import com.ys.enume.flow.YspTaskAuditUserEnum;
import com.ys.mapper.flow.FlowMapper;
import com.ys.service.business.TaskService;
import com.ys.service.flow.YspTaskService;
import com.ys.util.DateUtil;
import com.ys.util.jwt.JwtUtil;
import com.ys.vo.A;
import com.ys.vo.R;

import lombok.AllArgsConstructor;
import lombok.Data;

@Controller
@RequestMapping("/api/inter/task")
public class ApiInterTaskController {
	private static final Logger logger = LoggerFactory.getLogger(ApiInterTaskController.class);


	@Autowired
	private TaskService taskService;
    @Autowired
    private YspTaskService yspTaskService;
	@Autowired
	private FlowMapper flowMapper;

	//错误信息
	private Function<String,String> errorMsg = e-> e==null||"".equals(e)? "系统出错！": "单号【"+e+"】，系统出错！" ;
	
    @RequestMapping("/listTask")
	@ResponseBody
	public A listTask(
			HttpServletRequest request,
			String searchText,
			Integer pageNo,
			Integer stateAll  // 0待处理1已处理2已完成3制单中
			) {
		try {
			pageNo = pageNo == null ? 0 : pageNo - 1;

			String loginUserId = JwtUtil.getUserIdFromRequest(request);

			YsProcInst cond = new YsProcInst();
			if (stateAll == 0) {
				cond.setStateFlow(YsProcInstEnum.StateFlow.PROCESS.value);
				if ("admin".equals(loginUserId)) {
					cond.where("A.TaskId in (select TaskId from YSP_TaskAuditUser where State = " + YspTaskAuditUserEnum.State.FOR_AUDIT.value + ")");
				} else {
					cond.where("A.TaskId in (select TaskId from YSP_TaskAuditUser where UserId = '" + loginUserId + "' and State = " + YspTaskAuditUserEnum.State.FOR_AUDIT.value + ")");
				}
			} else if (stateAll == 1) {
				cond.where("A.StateFlow != " + YsProcInstEnum.StateFlow.FINISH.value);
				if ("admin".equals(loginUserId)) {
					cond.where("A.TaskId in (select TaskId from YSP_TaskAuditUser where State = " + YspTaskAuditUserEnum.State.SUCCESS.value + ")");
				} else {
					cond.where("A.TaskId in (select TaskId from YSP_TaskAuditUser where UserId = '" + loginUserId + "' and State = " + YspTaskAuditUserEnum.State.SUCCESS.value + ")");
				}
			} else if (stateAll == 2) {
				cond.setStateFlow(YsProcInstEnum.StateFlow.FINISH.value);
				if ("admin".equals(loginUserId)) {
				} else {
					cond.where("A.TaskId in (select TaskId from YSP_TaskAuditUser where UserId = '" + loginUserId + "')");
				}
			}

			if (searchText != null && searchText.length() > 0) {
//			cond.where("A.Bid like '%" + searchText + "%'");
				cond.where("(B.Name like '%" + searchText + "%' OR A.Bid like '%" + searchText + "%')");
			}

			cond = cond
					.addLeftJoin("YSP_Def B ON B.Id = A.DefId")
					.addField("B.Name defName")
					.addLeftJoin("TS_UserInfo C ON C.UserId = A.CreateUserId")
					.addField("C.UserName createUserName")
					.setOrderby("A.Id DESC");

			int totalNum = 0;

			//获取数量
			if(pageNo == 0 && stateAll == 0){
				totalNum = cond.count();
			}

			//获取列表信息
			List<Map<String, Object>> listEntity = cond
					.setSize(5)
					.setPage(pageNo)
					.queryMap();

			List<ListTaskDto.DetailDto> detailArr = new ArrayList<ListTaskDto.DetailDto>();
			if(listEntity!=null && listEntity.size()>0){
				for(Map<String, Object> map : listEntity) {
					YsProcInst entity = (YsProcInst) MapUtil.mapToObject(map, YsProcInst.class);
					String bid = entity.getBid();
					String title = map.get("defName").toString() + "(" + bid + ")";
					String createUser = (map.get("createUserName")!=null?map.get("createUserName").toString():"") + "(" + entity.getCreateUserId() + ")";
					String auditState = YsProcInstEnum.StateFlow.getName(entity.getStateFlow());
					String beginTime = DateUtil.getYYYY_MM_DD_HH_mm_ss(entity.getCreateTime());
					String endTime = DateUtil.getYYYY_MM_DD_HH_mm_ss(entity.getUpdateTime());
					detailArr.add(new ListTaskDto.DetailDto(bid, title, createUser, auditState, beginTime, endTime));
				}
			}
			ListTaskDto dto = new ListTaskDto(totalNum,detailArr);
			return A.suc(dto);
		}catch (Exception e){
			logger.error("出错：",e.getMessage(),e);
			return A.err(errorMsg.apply(""));
		}
	}
	@Data
	@AllArgsConstructor
	public static class ListTaskDto {
		private Integer totalNum;//数量
		private List<DetailDto> detailArr; // 详情数组
		
		@Data
		@AllArgsConstructor
		public static class DetailDto {
			private String bid; // 单号
			private String title; // 格式：采购计划取消(CGQX-240101-1041)
			private String createUser; // 发起人，格式：费玉清(00123)
			private String auditState; // 审批结果
			private String beginTime; // 开始时间
			private String endTime; // 结束时间
		}
	}
	

	
    @RequestMapping("/taskLog")
	@ResponseBody
	public A taskLog(HttpServletRequest request,
			String bid) {
		try {
			YsProcInst ysProcInst = new YsProcInst().setBid(bid).queryFirst();

			// 任务审核点ID-审核用户 MAP
			Map<Long, List<YspTaskAuditUser>> MAP_AUDITID_LISTUSER = new HashMap<Long, List<YspTaskAuditUser>>();
			Map<String, String> MAP_ID_NAME = new HashMap<String, String>();
			{
				List<Map<String, Object>> listYspTaskAuditUser = new YspTaskAuditUser().setTaskId(ysProcInst.getTaskId())
						.addLeftJoin("TS_UserInfo B ON B.UserId = A.UserId")
						.addField("B.UserName userName")
						.queryMap();
				try {
					for(Map<String, Object> map : listYspTaskAuditUser) {
						YspTaskAuditUser yspTaskAuditUser = (YspTaskAuditUser) MapUtil.mapToObject(map, YspTaskAuditUser.class);
						Long taskAuditId = yspTaskAuditUser.getTaskAuditId();
						List<YspTaskAuditUser> listSub = MAP_AUDITID_LISTUSER.containsKey(taskAuditId) ? MAP_AUDITID_LISTUSER.get(taskAuditId) : new ArrayList<YspTaskAuditUser>();
						listSub.add(yspTaskAuditUser);
						MAP_AUDITID_LISTUSER.put(taskAuditId, listSub);
						MAP_ID_NAME.put(yspTaskAuditUser.getUserId(), map.get("userName").toString());
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}

			List<YspTaskAudit> listYspTaskAudit = new YspTaskAudit().setTaskId(ysProcInst.getTaskId()).queryList();

			List<TaskLogDto.RowDto> rows = new ArrayList<TaskLogDto.RowDto>();
			for(YspTaskAudit yspTaskAudit : listYspTaskAudit) {
				Integer state = yspTaskAudit.getState();
				String title = YspTaskAuditEnum.State.getName(yspTaskAudit.getState());
				String desc = DateUtil.getYYYY_MM_DD_HH_mm_ss(yspTaskAudit.getUpdateTime());
				List<YspTaskAuditUser> listYspTaskAuditUser = MAP_AUDITID_LISTUSER.get(yspTaskAudit.getId());
				YspDefNode yspDefNode = new YspDefNode().setId(yspTaskAudit.getNodeIdCurrent()).queryFirst();
				if (yspDefNode.getType() == YspDefNodeEnum.Type.END.value) {
					String auditUser = "";
					String auditUserName = "";
					rows.add(new TaskLogDto.RowDto(title, auditUser,auditUserName, state, desc));
				} else {
					for(YspTaskAuditUser yspTaskAuditUser : listYspTaskAuditUser) {
						Integer yspTaskAuditUserState = yspTaskAuditUser.getState();
						if (yspTaskAuditUserState != YspTaskAuditUserEnum.State.NO_USE.value) {
							TsUserInfo tsUserInfo = new TsUserInfo().setUserId(yspTaskAuditUser.getUserId()).queryFirst();
							String auditUser = tsUserInfo.getUserId();
							String auditUserName = tsUserInfo.getUserName();
							rows.add(new TaskLogDto.RowDto(title, auditUser,auditUserName, state, desc));
							break;
						}
					}
				}

			}

			Integer step = listYspTaskAudit.size() - 1;
			TaskLogDto dto = new TaskLogDto(step, rows);

			return A.suc(dto);
		}catch (Exception e){
			logger.error("出错：",e.getMessage(),e);
			return A.err(errorMsg.apply(""));
		}
	}
	@Data
	@AllArgsConstructor
	public static class TaskLogDto {
		
		private Integer step; // 当前步骤，0代表第一步
		private List<RowDto> rows; // 详情数组
		
		@Data
		@AllArgsConstructor
		public static class RowDto {
			private String title; // 审批结果
			private String auditUser; // 审批人
			private String auditUserName; // 审批人姓名
			private Integer state; // 状态
			private String desc; // 时间
		}
	}

	
    @RequestMapping("/taskDetail")
	@ResponseBody
	public A taskDetail(HttpServletRequest request,
			String bid){
		try {
			String loginUserId = JwtUtil.getUserIdFromRequest(request);

			Map<String, Object> map = new YsProcInst()
					.setBid(bid)
					.addLeftJoin("YSP_Def B ON B.Id = A.DefId")
					.addField("B.Name defName")
					.addLeftJoin("TS_UserInfo C ON C.UserId = A.CreateUserId")
					.addField("C.UserName createUserName")

					.addLeftJoin("YSP_Def D ON D.Id = A.DefId")
					.addLeftJoin("YSP_Deploy D1 ON D1.Id = D.DeployId")
					.addField("D1.ModelId modelId")

					.queryFirstMap();

			YsProcInst entity = (YsProcInst) MapUtil.mapToObject(map, YsProcInst.class);
			String title = map.get("defName").toString() + "(" + bid + ")";
			String createUser = ( map.get("createUserName")!=null?map.get("createUserName").toString():"") + "(" + entity.getCreateUserId() + ")";
			String auditState = YsProcInstEnum.StateFlow.getName(entity.getStateFlow());
			String beginTime = DateUtil.getYYYY_MM_DD_HH_mm_ss(entity.getCreateTime());
			String endTime = DateUtil.getYYYY_MM_DD_HH_mm_ss(entity.getUpdateTime());

			// 获取流程模型ID，并验证在菜单中的唯一性
			Long modelId = Long.parseLong(map.get("modelId").toString());
			if(new YsMenu().setFlowModelId(modelId).count() > 1) {
				return A.err("该流程模型有多个菜单在使用，请确认配置");
			}
			YsMenu ysMenu = new YsMenu().setFlowModelId(modelId).queryFirst();
			Long gridId = ysMenu.getGridId();
			// 字段数组
			List<TaskDetailDto.ColDto> sonCols = new ArrayList<TaskDetailDto.ColDto>();
			List<YsGridCol> listYsGridCol = new YsGridCol().setGridId(gridId)
					.setOrderby("A.SortNo asc")
					.setAppFrontShow(1)
					.queryList();
			for(YsGridCol ysGridCol : listYsGridCol) {
				String code = ysGridCol.getCode();
				String name = ysGridCol.getName();
				Integer width = ysGridCol.getAppFrontWidth();
				Integer isShow = ysGridCol.getAppFrontShow(); // 是否显示
				String frontType = ysGridCol.getAppFrontType(); // 显示类型
				String dictKey = ysGridCol.getDictKeyBase()!=null?ysGridCol.getDictKeyBase():"";
				String align = YsGridColEnum.FrontAlign.getLayerAlign(ysGridCol.getAppFrontAlign()); // 显示位置
				Integer sourceType = ysGridCol.getMultyFileSourceType();
				sonCols.add(new TaskDetailDto.ColDto(code, name, width,isShow,frontType,dictKey,align,sourceType));
			}

			/*
			 * 数据数组，根据不同
			 */
			Long menuId = ysMenu.getId();
			List<Map<String, Object>> sonlist = taskService.sonlist(menuId, bid);

			Map<String, Object> fromInfo = taskService.fromInfo(menuId, bid);// 母表数据

			// 字段数组
			List<TaskDetailDto.ColDto> cols = new ArrayList<TaskDetailDto.ColDto>();
			List<YsCol> listYsCol = new YsCol()
					.setMenuId(menuId)
					.setAppFormState(1)
					.setOrderby("A.SortNo asc")
					.queryList();
			for(YsCol ysCol : listYsCol) {
				String code = ysCol.getCode();
				String name = ysCol.getName();
				Integer width = ysCol.getFrontWidth();
				Integer isShow = ysCol.getAppFormState(); // 是否显示
				String frontType = ysCol.getAppFormType(); // 显示类型
				String dictKey = ysCol.getDictKeyBase()!=null?ysCol.getDictKeyBase():"";
				String align = ""; // 显示位置
				Integer sourceType = ysCol.getMultyFileSourceType();
				cols.add(new TaskDetailDto.ColDto(code, name, width,isShow,frontType,dictKey,align,sourceType));
			}


			//获取字典数据
			List<Map<String, Object>> dictInfoNoGroup = new YsDict().setStatus(1).setOrderby("A.DictKey ASC,A.SortNo ASC").queryMap();
			//按照 字典key 分组
			Map<String, List<Map<String, Object>>> dictInfo = dictInfoNoGroup.stream().collect(Collectors.groupingBy(e->e.get("dictKey").toString()));

			//获取下一个审批节点的数据
			Map<String, Object> nextInfo =  yspTaskService.getNextTaskAuditUser(loginUserId,bid);

			List<Map<String, Object>> nextAuditUser = new ArrayList<>();
			boolean isEnd = false;

			if(nextInfo!=null && (Boolean) nextInfo.get("isError") == false ){
				isEnd = (Boolean) nextInfo.get("isEnd");
				nextAuditUser = (List<Map<String, Object>>) nextInfo.get("userList");
			}

			TaskDetailDto dto = new TaskDetailDto(bid, title, createUser, auditState, beginTime, endTime,nextAuditUser, isEnd,dictInfo,cols, fromInfo, sonCols, sonlist);

			return A.suc(dto);
		}catch (Exception e){
			logger.error("出错：",e.getMessage(),e);
			return A.err(errorMsg.apply(""));
		}
	}
	@Data
	@AllArgsConstructor
	public static class TaskDetailDto {
		
		private String bid; // 单号
		private String title; // 格式：采购计划取消(CGQX-240101-1041)
		private String createUser; // 发起人，格式：费玉清(00123)
		private String auditState; // 审批结果
		private String beginTime; // 开始时间
		private String endTime; // 结束时间
		private List<Map<String, Object>> nextAuditUser;// 下一个审批人
		private boolean isEnd;//是否是最后一个审批节点
        Map<String, List<Map<String, Object>>> dictInfo;//字典表数据
		private List<ColDto> cols; // 母表字段数组
		private Map<String, Object> fromInfo; // 母表数据
		private List<ColDto> sonCols; // 子列表字段数组
		private List<Map<String, Object>> sonlist; // 子列表数组
		
		@Data
		@AllArgsConstructor
		public static class RowDto {
			private String title; // 审批结果
			private String auditUser; // 审批人
			private Integer state; // 状态
			private String desc; // 时间
		}
		
		@Data
		@AllArgsConstructor
		public static class ColDto {
			private String code; // 编码
			private String name; // 名称
			private Integer width; // 宽度
			private Integer isShow; // 是否显示
			private String frontType; // 显示类型
            private String dictKey; // 字典key
            private String align; // 显示位置
			private Integer sourceType;//多个附件上传的来源类型
		}
	}

	
	/*
	 * 审核通过
	 */
    @RequestMapping("/taskFlowPass")
	@ResponseBody
	public A taskFlowPass(HttpServletRequest request,
			String bid) {
    	Long menuId = flowMapper.getMenuIdByBid(bid);
    	String userId = JwtUtil.getUserIdFromRequest(request);
    	try {
    		R r = taskService.taskFlowPass(menuId,userId,bid);
    		
    		if (r.getCode() == R.Code.FAILED.value) {
				return A.err(r.getMsg());
			} else {
				return A.suc("操作成功");
			}
		} catch (IllegalArgumentException e) {
			logger.error("出错：",e.getMessage(),e);
			return A.err(e.getMessage());
		} catch (Exception e){
			logger.error("出错：",e.getMessage(),e);
			return A.err(errorMsg.apply(bid));
		}
    }

	
	/*
	 * 审核退回
	 */
    @RequestMapping("/taskFlowRefuse")
	@ResponseBody
	public A taskFlowRefuse(HttpServletRequest request,
			String bid, String reason) {
		
    	Long menuId = flowMapper.getMenuIdByBid(bid);
    	String userId = JwtUtil.getUserIdFromRequest(request);
    	
    	try {
    		R r = taskService.taskFlowRefuse(menuId,userId,bid,reason);

    		if (r.getCode() == R.Code.FAILED.value) {
				return A.err(r.getMsg());
			} else {
				return A.suc("操作成功");
			}
		} catch (IllegalArgumentException e) {
			logger.error("出错：",e.getMessage(),e);
			return A.err(e.getMessage());
		} catch (Exception e){
			logger.error("出错：",e.getMessage(),e);
			return A.err(errorMsg.apply(bid));
		}
    }



	/*
	 * 审核驳回
	 */
	@RequestMapping("/taskFlowInit")
	@ResponseBody
	public A taskFlowInit(HttpServletRequest request,
							String bid, String reason) {

		Long menuId = flowMapper.getMenuIdByBid(bid);
		String userId = JwtUtil.getUserIdFromRequest(request);

		try {
			R r = taskService.taskFlowInit(menuId,userId,bid,reason);

			if (r.getCode() == R.Code.FAILED.value) {
				return A.err(r.getMsg());
			} else {
				return A.suc("操作成功");
			}
		} catch (IllegalArgumentException e) {
			logger.error("出错：",e.getMessage(),e);
			return A.err(e.getMessage());
		} catch (Exception e){
			logger.error("出错：",e.getMessage(),e);
			return A.err(errorMsg.apply(bid));
		}
	}
}
